package com.voda.dao.impl.common;

import java.util.List;

import javax.persistence.PersistenceException;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;

import com.voda.dao.api.IGenericDao;
import com.voda.entity.api.IBaseEntity;


/**
 * The Class AbstractDao.
 *
 * @param <T> the generic type
 */
public abstract class AbstractDaoImpl<T extends IBaseEntity> implements IGenericDao<T>{
	
	/** The session factory. */
	@Autowired
    protected SessionFactory sessionFactory;
	
	/** The clazz. */
	@SuppressWarnings("rawtypes")
	protected final Class clazz;
	
	/**
	 * Instantiates a new abstract dao.
	 *
	 * @param clazz the clazz
	 */
	@SuppressWarnings("rawtypes")
	public AbstractDaoImpl(Class clazz) {
		this.clazz = clazz;
	}

	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#addRecord(com.voda.entity.api.IBaseEntity)
	 */
	@Override
	public Long addRecord(T entity) throws PersistenceException {
		try {
			return (Long) getSession().save(entity);
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#deleteRecord(java.lang.Long)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void deleteRecord(Long id) throws PersistenceException {
		try {
			T entity = (T) getSession().load(clazz, id);
			getSession().delete(entity);
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#updateRecord(com.voda.entity.api.IBaseEntity)
	 */
	@Override
	public void updateRecord(T entity) throws PersistenceException {
		try {
			getSession().update(entity);
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#getRecordById(java.lang.Long)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public T getRecordById(Long id) throws PersistenceException {
		try {
			return (T) getSession().get(clazz, id);
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#getRecordsPage(java.lang.Integer, java.lang.Integer)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> getRecordsPage(Integer startPage, Integer pageSize)
			throws PersistenceException {
		try {
			Criteria cr = getSession().createCriteria(clazz);
			cr.setFirstResult((startPage - 1) * pageSize);
			cr.setMaxResults(pageSize);
			return cr.list();
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}
	
	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#count()
	 */
	public Integer count(){
		try{
			List<?> list = getSession().createCriteria(clazz).setProjection(Projections.rowCount()).list();
			Long rowCount =(Long) list.get(0);
			return rowCount.intValue();
		} catch (Exception e){
			throw new PersistenceException();
		}
	}
	
	/* (non-Javadoc)
	 * @see com.voda.dao.api.IGenericDao#getAll()
	 */
	@SuppressWarnings("unchecked")
	public List<T> getAll()	{
		try {
			Criteria cr = getSession().createCriteria(clazz);
			return cr.list();
		} catch (Exception e) {
			throw new PersistenceException(e);
		}
	}
	
	/**
	 * Gets the session.
	 *
	 * @return the session
	 */
	protected Session getSession()	{
		return sessionFactory.getCurrentSession();
	}
	
	/**
	 * Gets the criteria.
	 *
	 * @return the criteria
	 */
	protected Criteria getCriteria(){
		return sessionFactory.getCurrentSession().createCriteria(clazz);
	}
}
